﻿using System;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Users;

namespace EcoSystem.CurrentUser
{

    /// <summary>
    /// 
    /// </summary>
    [ExposeServices(typeof(ICurrentUser))]
    public class IddictCurrentUser : ICurrentUser, ITransientDependency
    {
        private static readonly Claim[] EmptyClaimsArray = new Claim[0];

        private readonly ICurrentPrincipalAccessor _principalAccessor;

        public IddictCurrentUser(ICurrentPrincipalAccessor principalAccessor)
        {
            _principalAccessor = principalAccessor;
        }

        public bool IsAuthenticated => this.Id.HasValue;

        public Guid? Id
        {
            get
            {
                var userId = this.FindClaimValue(ClaimTypes.NameIdentifier);
                if (userId.IsNullOrWhiteSpace())
                {
                    return null;
                }

                if (Guid.TryParse(userId, out Guid guid))
                {
                    return guid;
                }
                return null;
            }
        }

        public string UserName => this.FindClaimValue(ClaimTypes.Name);

        public string Name => this.FindClaimValue(ClaimTypes.GivenName);

        public string SurName => this.FindClaimValue(ClaimTypes.Surname);

        public string PhoneNumber => this.FindClaimValue(AbpClaimTypes.PhoneNumber);

        public bool PhoneNumberVerified => string.Equals(this.FindClaimValue(AbpClaimTypes.PhoneNumberVerified), "true", StringComparison.InvariantCultureIgnoreCase);

        public string Email => this.FindClaimValue(ClaimTypes.Email);

        public bool EmailVerified => string.Equals(this.FindClaimValue(AbpClaimTypes.EmailVerified), "true", StringComparison.InvariantCultureIgnoreCase);

        public Guid? TenantId => _principalAccessor.Principal.FindTenantId();

        public string[] Roles => FindClaims(ClaimTypes.Role).Select(c => c.Value).Distinct().ToArray();

        public Claim FindClaim(string claimType)
        {
            return _principalAccessor.Principal?.Claims.FirstOrDefault(c => c.Type == claimType);
        }

        public Claim[] FindClaims(string claimType)
        {
            return _principalAccessor.Principal?.Claims.Where(c => c.Type == claimType).ToArray() ?? EmptyClaimsArray;
        }

        public Claim[] GetAllClaims()
        {
            return _principalAccessor.Principal?.Claims.ToArray() ?? EmptyClaimsArray;
        }

        public bool IsInRole(string roleName)
        {
            return FindClaims(ClaimTypes.Role).Any(c => c.Value == roleName);
        }
    }
}
